package com.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;



/**
 * @ClassName: NioServer
 * @Description:
 * @Date 2024/04/26 10:46
 * @Author songshaoqiu
 **/
public class NioServer {
    public static void main(String[] args) throws IOException {
        //创建severSocketChannel对象
        ServerSocketChannel ssc = ServerSocketChannel.open();
        //设置为非阻塞模式
        ssc.configureBlocking(false);
        //设置服务端程序绑定端口
        ssc.socket().bind(new InetSocketAddress(9091));
        //创建Selector多路复用器
        Selector selector = Selector.open();
        //将serverSocketChannel对象注册到Selector上，并且告知对客户端的连接这样的事件感兴趣
        ssc.register(selector, SelectionKey.OP_ACCEPT);

        while (true){
            System.out.println("等待事件发送");
            //阻塞，轮询监听所有注册到selector上的channel
            int select = selector.select();
            System.out.println("某个事件发生了");
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()){
                //一个SocketChannel 对应一个selectionkey
                SelectionKey selectionKey = iterator.next();
                handleMethod(selectionKey);
                iterator.remove();;
            }
        }

    }

    private static void handleMethod(SelectionKey selectionKey) throws IOException {
        //判断channel上发生了什么事件
        //如果是服务端连接客户端事件
        if (selectionKey.isAcceptable()){
            System.out.println("客户端:"+selectionKey+"的连接事件");
            //服务端处理客户端的连接，得到ServerSocketChannel,代表着服务器
            ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
            //服务端接口客户端的连接，得到客户端的channel
            SocketChannel channel = serverSocketChannel.accept();
            //把channel 设置成非阻塞的
            channel.configureBlocking(false);
            //服务端拿到这个客户端的channel,然后注册 读取事件，也就是 客户端的写信息
            SelectionKey register = channel.register(selectionKey.selector(), SelectionKey.OP_READ );
        }else if (selectionKey.isReadable()){
            System.out.println("客户端向服务器端写数据");
            SocketChannel channel = (SocketChannel) selectionKey.channel();
            ByteBuffer readByteBuffer = ByteBuffer.allocate(1024);
            int read = channel.read(readByteBuffer);
            if (read!=-1){
                System.out.println("服务端读取客户端写的数据:"+new String(readByteBuffer.array(),0,read));
            }
            //服务器端向客户端返回数据
            ByteBuffer writeBuffer = ByteBuffer.wrap("hello client".getBytes());
            channel.write(writeBuffer);
            //监听下一次事件 读or写
            selectionKey.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE);
        }

    }


















    
}
